home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_09_04 / 9n04066a < prev    next >
Text File  |  1990-12-17  |  9KB  |  208 lines

  1. #include <dos.h>
  2. #include <stdio.h>
  3. #define   COM_PORT          2   /* serial port definitions for COM2 */
  4. #define   COMPARMS       0x83   /* comm. parameters for 1200-n-8-1  */
  5. #include "serial.h"  /* definitions and constants for this program  */
  6.  
  7.  
  8. main()      /* main program initializes the hardware, then enters a */
  9. {        /* loop where it moves characters from receive serial port */
  10. int ch;     /* to screen, and from keyboard to transmit serial port */
  11.  
  12.   install();      /* install interrupt handler, initialize COM port */
  13.   atexit(cleanup);/* post removal routine to execute at program end */
  14.  
  15.   while( 1 ) {           /* main program loop, repeat over and over */
  16.  
  17.     while ((ch = sgetch()) != S_EOF) {  /* if serial char available */
  18.       putch(ch);                        /* put it on the screen     */
  19.       if (translation && ch == '\r')    /* if translation in effect */
  20.         putch('\n');                    /* add line feeds to C/R's  */
  21.     }
  22.  
  23.     if (kbhit()) { /* keyboard handler, execute if key has been hit */
  24.  
  25.       ch = getch();         /* read the character from the keyboard */
  26.       if (ch == 0)          /* if zero, next character is scan code */
  27.         switch (ch = getch()) { /* read scan code from the keyboard */
  28.  
  29.           case 0x12:                      /* if character is Alt-E  */
  30.             echo = !echo;                 /* toggle the screen echo */
  31.             if (echo) printf("\nEcho on.\n");
  32.             else printf("\nEcho off.\n");
  33.             break;
  34.  
  35.           case 0x14:                      /* if character is Alt-T  */
  36.             translation = !translation;   /* toggle the translation */
  37.             if (translation) printf("\nTranslation on.\n");
  38.             else printf("\nTranslation off.\n");
  39.             break;
  40.                                           /* if character is Alt-S  */
  41.           case 0x1f:                      /* print the modem status */
  42.             ch = inportb(ACE_MODEM_STAT_REG); /* get current status */
  43.             printf("\nStatus:  DCD=%1d DSR=%1d CTS=%1d\n",
  44.               (ch & DCD) ? 1:0, (ch & DSR) ? 1:0, (ch & CTS) ? 1:0);
  45.             if (break_detect || frame_error
  46.                     || char_overrun || parity_error) {
  47.                 printf("Errors:\n");                /* error report */
  48.                 printf("  overrun      = %4d\n", char_overrun);
  49.                 printf("  frame error  = %4d\n", frame_error );
  50.                 printf("  break detect = %4d\n", break_detect);
  51.                 printf("  parity error = %4d\n", parity_error);
  52.                 break_detect = frame_error =
  53.                     char_overrun = parity_error = 0;
  54.             }
  55.             else printf("No errors.\n");
  56.             if (echo) printf("Echo on.\n");
  57.             if (translation) printf("Translation on.\n");
  58.             break;
  59.  
  60.           case 0x2d:                       /* if character is Alt-X */
  61.             exit();                        /* terminate the program */
  62.         }
  63.       else {     /* otherwise, the character was a normal character */
  64.         sputch(ch);         /* so send it to the serial transmitter */
  65.         if (echo) {                      /* if echo is on           */
  66.           putch(ch);                     /* echo char to the screen */
  67.           if (ch == '\r') putch('\n');   /* add line feeds to C/R's */
  68.         }
  69.       }
  70.     }                                    /* end of keyboard handler */
  71.  
  72.     if (ring_detect) {     /* if ring is detected, beep the speaker */
  73.       putch('\a');         /* requires modem cable pin 22 connected */
  74.       ring_detect = 0;     /* then reset ring detect for next time  */
  75.     }
  76.   }
  77. }
  78.  
  79.  
  80.  
  81. void interrupt serial_isr(void)   /* interrupt service routine      */
  82. {                                 /* executed when receive data is  */
  83. char ch;                          /* available, or when line status */
  84. int temp_index;                   /* or modem status changes        */
  85.  
  86.   enable();                       /* re-enable the other interrupts */
  87.  
  88.   ch = inportb(ACE_INT_IDENT_REG); /* examine IIR for cause of int. */
  89.   switch (ch) {
  90.  
  91.     case 6:                            /* if line status interrupt  */
  92.       ch = inportb(ACE_LINE_STAT_REG); /* read line status register */
  93.       if (ch & PE) parity_error++;     /* then increment the error  */
  94.       if (ch & OE) char_overrun++;     /* counters according to     */
  95.       if (ch & FE) frame_error++;      /* which error bits are set  */
  96.       if (ch & BI) break_detect++;
  97.       inportb(ACE_DATA_REG);  /* read the data register to empty it */
  98.       break;
  99.  
  100.     case 4:                         /* if received data available   */
  101.       ch = inportb(ACE_DATA_REG);   /* read character from the ACE  */
  102.       temp_index = input_index + 1; /* temporary value              */
  103.       if (temp_index >= QUELEN)     /* test for index past buf. end */
  104.         temp_index = 0;             /* if so, reset to beginning    */
  105.       if (temp_index != output_index) { /* test for queue overflow  */
  106.         queue[temp_index] = ch;         /* put character into queue */
  107.         input_index = temp_index;       /* and update the index     */
  108.       }              /* if the queue overflows, characters are lost */
  109.       break;
  110.  
  111.     case 0:                            /* if modem status interrupt */
  112.       ch = inportb(ACE_MODEM_STAT_REG);   /* read modem status reg. */
  113.       if (ch & DCTS) {                  /* if clear to send changed */
  114.                      /* a routine to handle CTS changes may go here */
  115.       }
  116.       if (ch & DDSR) {                 /* if data set ready changed */
  117.                      /* a routine to handle DSR changes may go here */
  118.       }
  119.       if (ch & TERI) {       /* if trailing edge ring indicator was */
  120.         ring_detect = 1;           /* asserted, turn on ring detect */
  121.       }
  122.       if (ch & DDCD) {            /* if data carrier detect changed */
  123.                      /* a routine to handle DCD changes may go here */
  124.       }
  125.   }
  126.  
  127.   outportb(PIC_CTL_REG, NON_SPEC_EOI);         /* finally, send the */
  128.                            /* non-specific EOI to re-enable the PIC */
  129. }
  130.  
  131.  
  132.  
  133. int sgetch(void)   /* read a character from the serial input buffer */
  134. {
  135. char ch;
  136. int temp_index;     /* temporary index value avoids a conflict with */
  137.                     /* interrupt routine updating the same variable */
  138.  
  139.   if (output_index != input_index) {  /* test for char. available   */
  140.     temp_index = output_index + 1;    /* increment temporary index  */
  141.     if (temp_index >= QUELEN)         /* is index past buffer end ? */
  142.       temp_index = 0;                 /* if so, reset to beginning  */
  143.     ch = queue[temp_index];           /* get character from buffer  */
  144.     output_index = temp_index;        /* update the output index    */
  145.     return(ch);                       /* character is return value  */
  146.   }
  147.   else return(S_EOF);   /* if no chars available, return serial EOF */
  148. }
  149.  
  150.  
  151.  
  152. void sputch(char ch)    /* output a character to serial transmitter */
  153. {
  154.   while( inportb(ACE_LINE_STAT_REG) & THRE == 0 ) /* buffer empty ? */
  155.     ;             /* if transmit buffer not empty, wait, do nothing */
  156.   outportb(ACE_DATA_REG, ch);  /* when empty, send char to the 8250 */
  157. }
  158.  
  159.  
  160.  
  161. void install(void)    /* installs the interrupt service routine and */
  162. {                 /* initializes the 8250 for active communications */
  163. char ch;
  164.  
  165.   bioscom(0, COMPARMS, COM_PORT - 1); /* set communications params. */
  166.  
  167.   /* enable ACA modem status, line status & receive data interrupts */
  168.   outportb(ACE_INT_ENB_REG, 0xd); /* enable modem/line/rcvdata ints */
  169.   inportb(ACE_DATA_REG);          /* empty receive data register    */
  170.   inportb(ACE_LINE_STAT_REG);     /* clear the line status register */
  171.  
  172.   old_vector = getvect(COM_INT_NUM);   /* save previous int. vector */
  173.   setvect(COM_INT_NUM, *serial_isr);   /* set vector to our routine */
  174.  
  175.   ch = inportb(PIC_INT_MASK_REG);   /* get current interrupt mask   */
  176.   ch &= IRQ_MASK;                   /* unmask our IRQ (set it to 0) */
  177.   outportb(PIC_INT